{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "NOTE: This lab references some (commercial) training material on [ChipWhisperer.io](https://www.ChipWhisperer.io). You can freely execute and use the lab per the open-source license (including using it in your own courses if you distribute similarly), but you must maintain notice about this source location. Consider joining our training course to enjoy the full experience.\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SUMMARY:** *In earlier labs, we have use the existing trigger mechanisms. What happens as you move to real-life? You'll likely want to use some of the triggering mechanisms discussed in the course. One such method is to actually trigger on serial data transfers.*\n",
    "\n",
    "*The following lab is applicable only to ChipWhisperer-Lite (including both the -Arm, -Xmega, and verions included in SCAKIT-L1 and SCAKIT-L2). You can run this lab with the ChipWhisperer-Pro as well, but note you can use additional trigger modes (such as triggering on specific data), that will give you even more reliable triggers. The ChipWhisperer-Nano has a fixed trigger input, so cannot use the UART trigger options.*\n",
    "\n",
    "**LEARNING OUTCOMES:**\n",
    "\n",
    "* Exporing the Trigger Circuitry of the ChipWhisperer-Lite.\n",
    "* Triggering on the UART data flow.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## About Simple-Serial Protocol"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This lab will attack our protocol used in previous labs. Unlike previous labs (where we had a 'magic trigger'), we'll need to trigger on the UART communication.\n",
    "\n",
    "To summarize, the general flow of the Simple-Serial Protocol is something like the following, where `→` means a transmission TO the target, and `←` means a response FROM the target.\n",
    "\n",
    "    → p00112233445566778899AABBCCDDEEFF\\n\n",
    "    ← r0123456789ABCDEF1122334455667788\\n\n",
    "    ← z00\\n\n",
    "\n",
    "The encryption operation happens somewhere between sending `p112233445566778899AABBCCDDEEFF\\n` and receiving `r0123456789ABCDEF11223344556677\\n`. In this case, the above protocol sequence means: \n",
    "\n",
    "1. A `p`laintext of `0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF` was sent to the target.\n",
    "2. The target encrypted this plaintext.\n",
    "3. The `r`esulting ciphertext is `0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88`.\n",
    "4. The command was ACK'd with a `z` of `0x00`, where `0x00` in this case means command was successsful.\n",
    "\n",
    "The encryption key was sent seperately in this example, but would have been sent with a `k` message similar to above.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Talking to the Target"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In lab 4.N, we use the built-in command `trace = cw.capture_trace(scope, target, text, key)` to capture a trace. This command assumes normal triggering based on an external IO line, and the communication protocol defined above.\n",
    "\n",
    "If we attach an oscilloscope to the data lines, we can see the specific data being transferred, where we have the `TX` line, the normal trigger routed to `GPIO4`, the `RX` line, and the power measurement:\n",
    "\n",
    "<img src=\"img/uart_triggers.png\" alt=\"UART Trigger\" width=\"750\"/>\n",
    "\n",
    "Notice something there? We could trigger on the IO lines to accomplish the same goal! While the `GPIO4` line shows exactly where the encryption is occuring, there is some very obvious falling edges around both the `TX` and `RX` lines before and after the encryption operation.\n",
    "\n",
    "The timing isn't as perfect (some delay before the first falling edge of TX for example and the encryption), but it looks like it could work.\n",
    "\n",
    "As we discussed in the course slides & video - there is a difference between triggering on the \"TX\" and \"RX\" sides. We expect that TX will have a little jitter, so if we can get RX working this will be even better."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to the Hardware"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As before - you'll need to connect to the hardware. To summarize the previous labs (in case you jumped ahead to this), this can be one of the following setups:\n",
    "\n",
    "* ChipWhisperer-Lite XMEGA\n",
    "* ChipWhisperer-Lite 32-bit (Arm)\n",
    "* ChipWhisperer-Lite Capture with CW308 UFO Board using:\n",
    "   * STM32F303 Target Board (same as `CWLITEARM`)\n",
    "   * XMEGA Target Board (same as `CWLITEXMEGA`)\n",
    "   * Any other target board (only the two above are 'tested').\n",
    "* ChipWhisperer-Pro Capture with CW308 UFO Board using:\n",
    "   * STM32F303 Target Board (same as `CWLITEARM`)\n",
    "   * XMEGA Target Board (same as `CWLITEXMEGA`)\n",
    "   * Any other target board (only the two above are 'tested').\n",
    "\n",
    "You shouldn't need to change `SCOPETYPE` below, but you'll need to change `PLATFORM` to either `CWLITEARM` or `CWLITEXMEGA`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "SCOPETYPE = 'OPENADC'\n",
    "PLATFORM = 'CW308_SAM4S'\n",
    "CRYPTO_TARGET='TINYAES128C'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash -s \"$PLATFORM\" \"$CRYPTO_TARGET\"\n",
    "cd ../../../firmware/mcu/simpleserial-aes\n",
    "make PLATFORM=$1 CRYPTO_TARGET=$2 -j"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%run \"../../Setup_Scripts/Setup_Generic.ipynb\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "cw.program_target(scope, prog, \"../../../firmware/mcu/simpleserial-aes/simpleserial-aes-{}.hex\".format(PLATFORM))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Normal Capture Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's start with our existing capture. Confirm the following works before we start messing with things.\n",
    "\n",
    "This makes an interactive plot, and then plots FOUR traces over-top of each other. This should look very similar to our previous power captures.\n",
    "\n",
    "If you get in trouble later, run the block above that reconnects (you can skip programming)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pipe = Pipe(data=[])\n",
    "plot = cw.plot([1, 2, 3])\n",
    "dynamic_map = hv.DynamicMap(plot, streams=[pipe])\n",
    "plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import holoviews as hv\n",
    "from holoviews.streams import Pipe, Buffer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "pipe.send([1, 2, 3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "fig = hv.render(plot)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib notebook\n",
    "import matplotlib.pylab as plt\n",
    "\n",
    "fig = plt.figure()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm.notebook import trange\n",
    "import numpy as np\n",
    "import time\n",
    "\n",
    "reset_target(scope)\n",
    "\n",
    "fig.clf()\n",
    "ktp = cw.ktp.Basic()\n",
    "key, text = ktp.next()\n",
    "target.simpleserial_write('k', key)\n",
    "\n",
    "N = 4\n",
    "for i in trange(N, desc='Capturing traces'):\n",
    "    \n",
    "    scope.arm()\n",
    "    target.simpleserial_write('p', text)    \n",
    "    \n",
    "    ret = scope.capture()\n",
    "    if ret:\n",
    "        print(\"Target timed out!\")\n",
    "        continue\n",
    "\n",
    "    response = target.simpleserial_read('r', 16)\n",
    "        \n",
    "    trace = scope.get_last_trace()\n",
    "    \n",
    "    #plt.clf()\n",
    "    plt.plot(trace)\n",
    "    fig.canvas.draw()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Changing Clocks & Observing Waveforms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Before we change triggers around, let's play with clocks and samples used. We need to remember a few specific features:\n",
    "\n",
    "* Samples.\n",
    "* Offsets.\n",
    "* Pre-samples.\n",
    "* Clock sources for ADC.\n",
    "\n",
    "First - let's print a few relevant scope details:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"* scope.adc settings:\")\n",
    "print(scope.adc)\n",
    "\n",
    "print(\"* scope.clock settings:\")\n",
    "print(scope.clock)\n",
    "\n",
    "print(\"ADC Clock frequency: \" + str(scope.clock.adc_freq / 1E6) + \" MS/s\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Changing number of Samples\n",
    "\n",
    "```python\n",
    "    # Set number of samples to 24000 (max on CW-Lite)\n",
    "    scope.adc.samples = 24000\n",
    "```\n",
    "\n",
    "#### Positive offset\n",
    "\n",
    "We'll use `scope.adc.offset` to delay capture:\n",
    "\n",
    "```python\n",
    "    # Delay capture of ADC data a certain number of cycles\n",
    "    scope.adc.offset = 20000\n",
    "```\n",
    "    \n",
    "#### Negative offset\n",
    "\n",
    "Finally, set `scope.adc.presamples` to some larger number`:\n",
    "\n",
    "```python\n",
    "    # Presamples gives us a negative offset effectively\n",
    "    scope.adc.offset = 0\n",
    "    scope.adc.presamples = 20000\n",
    "```\n",
    "\n",
    "Try each of the above in the following block - there is the plotting block right after it, so you can keep re-running the following 3 blocks in sequence to easily see your code changes:    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#Put the stuff you are experimenting with right here.\n",
    "\n",
    "raise NotImplementedError(\"Add Your Code Here\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We copied the above capture loop below for you so you can just run the following:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib notebook\n",
    "import matplotlib.pylab as plt\n",
    "\n",
    "fig = plt.figure()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm.notebook import trange\n",
    "import numpy as np\n",
    "import time\n",
    "\n",
    "reset_target(scope)\n",
    "\n",
    "fig.clf()\n",
    "ktp = cw.ktp.Basic()\n",
    "key, text = ktp.next()\n",
    "target.simpleserial_write('k', key)\n",
    "\n",
    "N = 4\n",
    "for i in trange(N, desc='Capturing traces'):\n",
    "    \n",
    "    scope.arm()\n",
    "    target.simpleserial_write('p', text)    \n",
    "    \n",
    "    ret = scope.capture()\n",
    "    if ret:\n",
    "        print(\"Target timed out!\")\n",
    "        continue\n",
    "\n",
    "    response = target.simpleserial_read('r', 16)\n",
    "        \n",
    "    trace = scope.get_last_trace()\n",
    "    \n",
    "    #plt.clf()\n",
    "    plt.plot(trace)\n",
    "    fig.canvas.draw()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Using `scope.clock.adc_src = \"clkgen_x1\"`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Using `clock.adc_src` we can run our ADC clock slower. The clock is still synchronously sampled, so we'll get very good power analysis results.\n",
    "\n",
    "But by running the ADC clock at x1 the target, instead of x4, we basically get 4 times as many useful sample points. When we switch our trigger from the super-focused trigger we'll need some 'breathing room' to find the actual location the interesting stuff is running.\n",
    "\n",
    "Run the following block, and then go up and run the capture test again. The first time you run the block, this should show the old ADC frequency of 29.4 MS/s. If you re-run it again later, the ADC will already be set to the slower frequency."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import time\n",
    "\n",
    "#Reset settings from above\n",
    "scope.adc.samples = 24000\n",
    "scope.adc.offset = 0\n",
    "scope.adc.presamples = 0\n",
    "\n",
    "print(\"Initial ADC clock:\")\n",
    "print(\" ADC Clock frequency: \" + str(scope.clock.adc_freq / 1E6) + \" MS/s\")\n",
    "\n",
    "scope.clock.adc_src = \"clkgen_x1\"\n",
    "\n",
    "#Give time for frequency counter to update, as clock.adc_freq is a frequency counter\n",
    "time.sleep(0.25)\n",
    "\n",
    "print(\"New ADC clock:\")\n",
    "print(\"  ADC Clock frequency: \" + str(scope.clock.adc_freq / 1E6) + \" MS/s\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Changing Trigger Item"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Final thing to do - change the trigger setting! As mentioned before, we're going to experiment with `tio1` and `tio2` pins.\n",
    "\n",
    "What do those pins actually do? Run the following to see the configuration for your board:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"tio1 function: \" + scope.io.tio1)\n",
    "print(\"tio2 function: \" + scope.io.tio2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In my case, `tio1` is `serial_rx`, and `tio2` is `serial_tx`. This could change depending on the target board you selected.\n",
    "\n",
    "This means that `tio1` would be used to trigger on data received FROM the target, and `tio2` for data sent TO the target.\n",
    "\n",
    "We can see the current settings of the trigger module by running the following block:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"scope.trigger:\\n\" + str(scope.trigger))\n",
    "print(\"scope.adc.basic_mode: \" + scope.adc.basic_mode)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Changing Capture Loop"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you check out the capture loop from above, you'll see the following code block. This code block will send data to the target, wait for the trigger, and then finish reading.\n",
    "\n",
    "```python\n",
    "    scope.arm()\n",
    "    target.simpleserial_write('p', text)\n",
    "\n",
    "    ret = scope.capture()\n",
    "    if ret:\n",
    "        print(\"Target timed out!\")\n",
    "        continue\n",
    "\n",
    "    response = target.simpleserial_read('r', 16)\n",
    "```\n",
    "\n",
    "We need to change this around a little bit. Instead, we need to call `scope.capture()` *after* the serial data exchange happened. We're doing this because `scope.arm()` still happens before the serial transmission, so the hardware is still capturing data.\n",
    "\n",
    "The problem is that `scope.capture()` blocks - the capture hardware is always ready to capture as soon as `scope.arm()` is called. But `scope.capture()` says \"now wait until you see the trigger\".\n",
    "\n",
    "In this case, we now want to do that blocking wait after the full transmission protocol happens. See the following, where `scope.capture()` is now after the `target.simpleserial_read()`:\n",
    "\n",
    "```python\n",
    "    scope.arm()\n",
    "    target.simpleserial_write('p', text)\n",
    "    \n",
    "    response = target.simpleserial_read('r', 16)\n",
    "\n",
    "    ret = scope.capture()\n",
    "    if ret:\n",
    "        print(\"Target timed out!\")\n",
    "        continue\n",
    "```\n",
    "\n",
    "The following series of plotting and capture should work with the existing trigger, right before we set a new trigger logic. Because we're going to be coming back to this - we're making this into it's own little capture block."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### New Capture Loop\n",
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib notebook\n",
    "import matplotlib.pylab as plt\n",
    "\n",
    "fig = plt.figure()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Insert your code here to perform changes in captures\n",
    "# for example - change the number of samples, change the offset, etc\n",
    "\n",
    "# A simple example - just changing the number of samples\n",
    "scope.adc.samples = 24000\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from tqdm.notebook import trange\n",
    "import numpy as np\n",
    "import time\n",
    "\n",
    "reset_target(scope)\n",
    "\n",
    "fig = cw.plot()\n",
    "ktp = cw.ktp.Basic()\n",
    "key, text = ktp.next()\n",
    "target.simpleserial_write('k', key)\n",
    "\n",
    "N = 4\n",
    "for i in trange(N, desc='Capturing traces'):\n",
    "    \n",
    "    scope.arm()\n",
    "    target.simpleserial_write('p', text)\n",
    "\n",
    "    response = target.simpleserial_read('r', 16)\n",
    "    \n",
    "    ret = scope.capture()\n",
    "    if ret:\n",
    "        print(\"Target timed out!\")\n",
    "        continue\n",
    "        \n",
    "    trace = scope.get_last_trace()\n",
    "    \n",
    "    #plt.clf()\n",
    "    plt.plot(trace)\n",
    "    fig.canvas.draw()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "### Trigger on Transmit Pin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's configure this for `tx` first. In this example, `tio2` is the transmit pin. Run the following block to set the trigger for use \"tio2\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.adc.basic_mode = \"falling_edge\"\n",
    "scope.trigger.triggers = \"tio2\"\n",
    "\n",
    "raise NotImplementedError(\"Comment this line out - then run this block & then re-run new capture loop just above!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's change `scope.adc.offset` - if we are capturing every ~24000 samples, you should be able to iterate through in blocks of around 20000 samples. So you could set this to `20000`, `40000`, `60000`, etc. Here's it's set to 0.\n",
    "\n",
    "Re-run the capture block above with new settings of `scope.adc.offset` - suggested to copy the follow setting code above, so you don't need to forget about re-running this block!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.adc.offset = 0\n",
    "\n",
    "scope.adc.offset = {20000, 40000, 60000, 80000, etc}\n",
    "raise NotImplementedError(\"Copy the scope.adc.offset line to the `New Capture Loop` section.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Most likely - you'll see some not very interesting looking power traces. These power traces have been captured during the serial transmission phase of data, not the AES phase. You'll need to move around (using the `offset`) to find data of interest. Here's what the not interesting figure looks like:\n",
    "\n",
    "<img src=\"img/4traces_aes_poortrigger.png\" alt=\"Poor Trigger\" width=\"450\"/>\n",
    "\n",
    "Eventually you should see some interesting looking data! The `offset` in the following was set to `60000`, but yours may be different. If you zoom into the power trace, you'll see some jitter on the trace, as things are not perfectly aligned:\n",
    "\n",
    "<img src=\"img/4traces_aes_clkx1_offset60000.png\" alt=\"Using Pre-Sample, Zoomed In\" width=\"450\"/>\n",
    "\n",
    "We can re-align the traces using techniques covered in the SCA201 course, to shift the power trace around such they all line up, letting us use this \"jittery\" trace in the attack.\n",
    "\n",
    "Or, we can use the receive pin technique discussed next."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Trigger on Receive Pin"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's configure this for `rx` first. In this example, `tio1` is the receive pin.\n",
    "\n",
    "We'll set the offset back to 0, and now use \"tio1\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.adc.basic_mode = \"falling_edge\"\n",
    "scope.trigger.triggers = \"tio1\"\n",
    "scope.adc.offset = 0\n",
    "\n",
    "raise NotImplementedError(\"Run this block & then re-run new capture loop just above!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Run the block above - you'll see a lack of interesting activity! So use a feature called 'presample' which allows us to sample \"before\" the trigger. The maximum number of pre-samples before is what we set `samples` to. So in this case we had up to `24000` samples, so we'll use `20000` pre-samples.\n",
    "\n",
    "Run this block - the re-run the capture block again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.adc.presamples = 20000\n",
    "\n",
    "raise NotImplementedError(\"Run this block & then re-run new capture loop just above!\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Hopefully, when you run the capture you will now have some more interesting looking data. For example, in my run there is an obvious AES run right in the middle of this:\n",
    "\n",
    "<img src=\"img/4traces_aes_clkx1_presample5000.png\" alt=\"Using Pre-Sample with CLKGEN=x1\" width=\"450\"/>\n",
    "\n",
    "This was taken with a `presample` of `20000`, in this case meaning the trigger happened right at 5000, right around when the interesting looking power trace happens. If we zoom in on it, you should hopefully see a nice reliable power trace:\n",
    "\n",
    "<img src=\"img/4traces_aes_clkx1_presample5000_zoom.png\" alt=\"Using Pre-Sample, Zoomed In\" width=\"450\"/>\n",
    "\n",
    "As discussed in the training video - this makes sense, because the receive trigger is being sent under control of the target device. But even with jitter in the power trace, we can easily recover it using some of the synchronization techniques discussed in course SCA201.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Next Steps\n",
    "\n",
    "This notebook only did the capture, it didn't run the actual attack! You can use the captured data to perform an actual attack of course as well.\n",
    "\n",
    "All the capture loops here don't have the data recording logic, so you'll need to go back and add that in. Don't forget how we had to change the location of `scope.capture()` when we modified the block.\n",
    "\n",
    "You can also look at using external trigger logic. The ChipWhisperer-Pro (CW1200) has more advanced trigger logic, including hardware trigger on specific data values of UART or SPI, along with analog power trace triggers. Other NewAE tools such as the PhyWhisperer-USB can be used to trigger on protocols such as USB."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "<small>NO-FUN DISCLAIMER: This material is Copyright (C) NewAE Technology Inc., 2015-2020. ChipWhisperer is a trademark of NewAE Technology Inc., claimed in all jurisdictions, and registered in at least the United States of America, European Union, and Peoples Republic of China.\n",
    "\n",
    "Tutorials derived from our open-source work must be released under the associated open-source license, and notice of the source must be *clearly displayed*. Only original copyright holders may license or authorize other distribution - while NewAE Technology Inc. holds the copyright for many tutorials, the github repository includes community contributions which we cannot license under special terms and **must** be maintained as an open-source release. Please contact us for special permissions (where possible).\n",
    "\n",
    "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.</small>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
